﻿'Copyright (c) 2009, Dario Rossa
'All rights reserved.
'
'Redistribution and use in source and binary forms, with or without modification,
'are permitted provided that the following conditions are met:
'    * Redistributions of source code must retain the above copyright notice,
'      this list of conditions and the following disclaimer.
'    * Redistributions in binary form must reproduce the above copyright notice,
'      this list of conditions and the following disclaimer in the documentation
'      and/or other materials provided with the distribution.
'    * Neither the name of Dario Rossa nor the names of its contributors may be
'      used to endorse or promote products derived from this software without
'      specific prior written permission.
'
'THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
'AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
'IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
'DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
'ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
'(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
'LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
'ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
'(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
'SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Imports DotNetNuke.UI.Modules
Imports DotNetNuke.Common
Imports DotNetNuke.Services.FileSystem
Imports DotNetNuke.Services.Localization
Imports DotNetNuke.Modules.Blog.Business
Imports BlogML.Xml
Imports System.Xml

''' <summary>
''' Performs export from the database to a BlogML format file.
''' </summary>
''' <remarks></remarks>
Partial Public Class Export
    Inherits ModuleUserControlBase

    Private myContext As ModuleInstanceContext = Me.ModuleContext
    Private myBlogController As New BlogController
    Private myEntryController As New EntryController
    Private myCommentController As New CommentController

    Enum MessageType
        ErrorMessage
        InfoMessage
        OkMessage
    End Enum

    ''' <summary>
    ''' Handles page load.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not Page.IsPostBack Then
            Dim folders As ArrayList = DotNetNuke.Common.Utilities.FileSystemUtils.GetFoldersByUser(myContext.PortalId, False, False, "READ, WRITE")
            For Each folder As FolderInfo In folders
                Dim FolderItem As New ListItem
                If folder.FolderPath = String.Empty Then
                    FolderItem.Text = Localization.GetString("Root", Me.LocalResourceFile)
                Else
                    FolderItem.Text = folder.FolderPath
                End If
                FolderItem.Value = folder.FolderPath
                cboFolders.Items.Add(FolderItem)
            Next
            Dim blogs As ArrayList = myBlogController.ListBlogs(myContext.PortalId, -1, True)
            If blogs.Count > 0 Then
                For Each blog As BlogInfo In blogs
                    cboBlogs.Items.Add(New ListItem(blog.Title, blog.BlogID.ToString))
                Next
            End If
        End If
    End Sub

    ''' <summary>
    ''' Handles user's clicks on the Cancel command.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub cmdCancel_Click(ByVal sender As Object, ByVal e As EventArgs) Handles cmdCancel.Click
        Response.Redirect(NavigateURL(), True)
    End Sub

    ''' <summary>
    ''' Handles user's clicks on the Export command.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub cmdExport_Click(ByVal sender As Object, ByVal e As EventArgs) Handles cmdExport.Click
        Dim BlogID As Integer = CType(cboBlogs.SelectedItem.Value, Integer)
        Dim myBlog As BlogInfo = myBlogController.GetBlog(BlogID)
        If myBlog IsNot Nothing Then
            Dim newBlogML As BlogMLBlog = ConvertBlog(myBlog)
            Dim FilePath As String = myContext.PortalSettings.HomeDirectoryMapPath
            FilePath &= cboFolders.SelectedItem.Value
            FilePath &= txtFile.Text
            Dim stream As XmlWriter = XmlWriter.Create(FilePath)
            BlogMLSerializer.Serialize(stream, newBlogML)
            LogEvent(Localization.GetString("ExportedFile", Me.LocalResourceFile) & ".", MessageType.OkMessage)
        End If
    End Sub

    ''' <summary>
    ''' Returns a BlogMLBlog object from a given BlogInfo object.
    ''' </summary>
    ''' <param name="SourceDnnBlog">The source DNN blog</param>
    ''' <returns>The equivalent BlogMLBlog</returns>
    ''' <remarks></remarks>
    Private Function ConvertBlog(ByVal SourceDnnBlog As BlogInfo) As BlogMLBlog
        Dim newBlogML As New BlogMLBlog
        newBlogML.Title = SourceDnnBlog.Title
        newBlogML.SubTitle = SourceDnnBlog.Description
        If SourceDnnBlog.ShowFullName Then
            newBlogML.Authors.Add(New BlogMLAuthor With {.Title = SourceDnnBlog.UserFullName})
        Else
            newBlogML.Authors.Add(New BlogMLAuthor With {.Title = SourceDnnBlog.UserName})
        End If
        newBlogML.DateCreated = SourceDnnBlog.Created
        AddCategories(newBlogML, SourceDnnBlog.BlogID)
        AddPosts(newBlogML, SourceDnnBlog.BlogID)
        Return newBlogML
    End Function

    ''' <summary>
    ''' Imports a DNN blog's child blogs into the BlogMLBlog category collection.
    ''' </summary>
    ''' <param name="TargetBlogML">The BlogMLBlog target blog</param>
    ''' <param name="SourceParentBlogID">The source DNN parent blog ID</param>
    ''' <remarks></remarks>
    Private Sub AddCategories(ByRef TargetBlogML As BlogMLBlog, ByVal SourceParentBlogID As Integer)
        Dim childBlogs As ArrayList = myBlogController.ListBlogs(myContext.PortalId, SourceParentBlogID, True)
        If childBlogs.Count > 0 Then
            For Each childBlog As BlogInfo In childBlogs
                Dim categoryML As New BlogMLCategory
                categoryML.Approved = childBlog.Public
                categoryML.DateCreated = childBlog.Created
                categoryML.Description = childBlog.Description
                categoryML.Title = childBlog.Title
                categoryML.ID = childBlog.BlogID.ToString
                categoryML.ParentRef = SourceParentBlogID.ToString
                TargetBlogML.Categories.Add(categoryML)
                LogEvent(Localization.GetString("ExportedCategory", Me.LocalResourceFile) & ": " & childBlog.Title, MessageType.OkMessage)
                AddPosts(TargetBlogML, childBlog.BlogID)
            Next
        End If
    End Sub

    ''' <summary>
    ''' Adds posts from a DNN blog to the given BlogMLBlog object.
    ''' </summary>
    ''' <param name="TargetBlogML">The target BlogMLBlog object</param>
    ''' <param name="SourceBlogID">The source DNN blog ID</param>
    ''' <remarks></remarks>
    Private Sub AddPosts(ByRef TargetBlogML As BlogMLBlog, ByVal SourceBlogID As Integer)
        Dim posts As ArrayList = myEntryController.ListAllEntriesByBlog(SourceBlogID)
        If posts.Count > 0 Then
            For Each post As EntryInfo In posts                
                TargetBlogML.Posts.Add(ConvertPost(post, TargetBlogML.Authors(0).Title))
                LogEvent(Localization.GetString("ExportedPost", Me.LocalResourceFile) & ": " & post.Title, MessageType.OkMessage)
            Next
        End If
    End Sub

    ''' <summary>
    ''' Converts a DNN blog post to a BlogMLPost object.
    ''' </summary>
    ''' <param name="SourceDnnPost">The source DNN blog post</param>
    ''' <param name="Author">The author's name</param>
    ''' <returns>The converted BlogMLPost object</returns>
    ''' <remarks></remarks>
    Private Function ConvertPost(ByVal SourceDnnPost As EntryInfo, ByVal Author As String) As BlogMLPost
        Dim newPostML As New BlogMLPost
        newPostML.Approved = SourceDnnPost.Published
        newPostML.Content.Text = SourceDnnPost.Entry
        newPostML.Categories.Add(New BlogMLCategoryReference With {.Ref = SourceDnnPost.BlogID.ToString})
        newPostML.Authors.Add(Author)
        newPostML.PostType = BlogML.BlogPostTypes.Normal
        newPostML.DateCreated = SourceDnnPost.AddedDate
        If SourceDnnPost.Description <> "" Then
            newPostML.Excerpt.Text = SourceDnnPost.Description
            newPostML.HasExcerpt = True
        Else
            newPostML.HasExcerpt = False
        End If
        newPostML.ID = SourceDnnPost.EntryID
        newPostML.PostUrl = SourceDnnPost.PermaLink
        Dim comments As ArrayList = myCommentController.ListComments(SourceDnnPost.EntryID, True)
        If comments.Count > 0 Then
            For Each comment As CommentInfo In comments
                If comment.Approved Or (chkUnapprovedComments.Checked And Not comment.Approved) Then
                    newPostML.Comments.Add(ConvertComment(comment))
                    LogEvent(Localization.GetString("ExportedComment", Me.LocalResourceFile) & ": " & comment.Title, MessageType.OkMessage)
                Else
                    LogEvent(Localization.GetString("FilteredOutComment", Me.LocalResourceFile) & ": " & comment.Title, MessageType.ErrorMessage)
                End If
            Next
        End If
        Return newPostML
    End Function

    ''' <summary>
    ''' Converts a DNN blog comment to a BlogMLComment object.
    ''' </summary>
    ''' <param name="SourceDnnComment">The source DNN blog comment</param>
    ''' <returns>The converted BlogMLComment object</returns>
    ''' <remarks></remarks>
    Private Function ConvertComment(ByVal SourceDnnComment As CommentInfo) As BlogMLComment
        Dim newComment As New BlogMLComment
        newComment.Approved = SourceDnnComment.Approved
        newComment.Content.Text = SourceDnnComment.Comment
        newComment.DateCreated = SourceDnnComment.AddedDate
        newComment.Title = SourceDnnComment.Title
        newComment.UserEMail = SourceDnnComment.Email
        newComment.UserName = SourceDnnComment.UserName
        newComment.UserUrl = SourceDnnComment.Website
        Return newComment
    End Function

    ''' <summary>
    ''' Displays information to the user about the code operation.
    ''' </summary>
    ''' <param name="Message">The message to display</param>
    ''' <param name="Type">The message type</param>
    ''' <remarks></remarks>
    Private Sub LogEvent(ByVal Message As String, ByVal Type As MessageType)
        ltlOutput.Text &= "<br/><img src=""" & ResolveUrl("~/DesktopModules/DnnBlogML/images/")
        Select Case Type
            Case MessageType.ErrorMessage
                ltlOutput.Text &= "cross"
            Case MessageType.InfoMessage
                ltlOutput.Text &= "information"
            Case MessageType.OkMessage
                ltlOutput.Text &= "tick"
        End Select
        ltlOutput.Text &= ".png"" />" & Message
    End Sub

End Class